package com.thinkgem.jeesite.common.utils;

import java.io.UnsupportedEncodingException;
import java.lang.Character.UnicodeBlock;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import com.thinkgem.jeesite.common.persistence.DataEntity;

/**
 * Java 完美判断中文字符
 * Java判断一个字符串是否有中文一般情况是利用Unicode编码(CJK统一汉字的编码区间：0x4e00–0x9fbb)的正则来做判断，但是其实这个区间来判断中文不是非常精确，因为有些中文的标点符号比如：，。等等是不能识别的
 * @description:
 * @author kool.zhao
 * @createDate 2017年2月8日;上午11:03:24
 */
public class CharUtil {

	public static void main(String[] args) {
//        String[] strArr = new String[] { "www.micmiu.com", "!@#$%^&*()_+{}[]|\"'?/:;<>,.", "！￥……（）——：；“”‘’《》，。？、", "不要啊", "やめて", "韩佳人", "???" };
//        for (String str : strArr) {
//            System.out.println("===========> 测试字符串：" + str);
//            System.out.println("正则判断结果：" + isChineseByREG(str) + " -- " + isChineseByName(str));
//            System.out.println("Unicode判断结果 ：" + isChinese(str));
//            System.out.println("详细判断列表：");
//            char[] ch = str.toCharArray();
//            for (int i = 0; i < ch.length; i++) {
//                char c = ch[i];
//                System.out.println(c + " --> " + (isChinese(c) ? "是" : "否"));
//            }
//        }
		
		System.out.println(isCharOrNumber("啊"));
		System.out.println(isCharOrNumber("É½¶«Ê¡×Ü¹«Ë¾"));
		System.out.println(isChinese("的"));
		System.out.println(isChinese("É½¶«Ê¡×Ü¹«Ë¾"));
    }
	
	public static boolean isCharOrNumber(String strName) {
		if (strName == null) {
	          return false;
	    }
		// 编译正则表达式
	    Pattern pattern = Pattern.compile("[0-9a-zA-Z]*");
	    Matcher matcher = pattern.matcher(strName);
		return matcher.matches();
	}
 
    // 根据Unicode编码完美的判断中文汉字和符号
    private static boolean isChinese(char c) {
        Character.UnicodeBlock ub = Character.UnicodeBlock.of(c);
        if (ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS || ub == Character.UnicodeBlock.CJK_COMPATIBILITY_IDEOGRAPHS
                || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_A || ub == Character.UnicodeBlock.CJK_UNIFIED_IDEOGRAPHS_EXTENSION_B
                || ub == Character.UnicodeBlock.CJK_SYMBOLS_AND_PUNCTUATION || ub == Character.UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS
                || ub == Character.UnicodeBlock.GENERAL_PUNCTUATION) {
            return true;
        }
        return false;
    }
 
    // 完整的判断中文汉字和符号
    public static boolean isChinese(String strName) {
        char[] ch = strName.toCharArray();
        for (int i = 0; i < ch.length; i++) {
            char c = ch[i];
            if (isChinese(c)) {
                return true;
            }
        }
        return false;
    }
 
    // 只能判断部分CJK字符（CJK统一汉字）
    public static boolean isChineseByREG(String str) {
        if (str == null) {
            return false;
        }
        Pattern pattern = Pattern.compile("[\\u4E00-\\u9FBF]+");
        return pattern.matcher(str.trim()).find();
    }
 
    // 只能判断部分CJK字符（CJK统一汉字）
    public static boolean isChineseByName(String str) {
        if (str == null) {
            return false;
        }
        // 大小写不同：\\p 表示包含，\\P 表示不包含
        // \\p{Cn} 的意思为 Unicode 中未被定义字符的编码，\\P{Cn} 就表示 Unicode中已经被定义字符的编码
        String reg = "\\p{InCJK Unified Ideographs}&&\\P{Cn}";
        Pattern pattern = Pattern.compile(reg);
        return pattern.matcher(str.trim()).find();
    }
	
	/**
	 * 
	 * 字符串转码：转成符合oracle us7ascii 的编码
	 * @param input
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String str2ISO88591(String str){
		if(str == null){
			return "";
		}
		
		try {
			return new String(str.getBytes("GBK"), "iso-8859-1");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	
	}
	
	/**
	 * 字符串转码：转换成与查询条件一直的
	 * @param search
	 * @return
	 * @throws UnsupportedEncodingException
	 */
	public static String ISO885912str(String str){
		if(str == null){
			return "";
		}
		
		try {
			return new String(str.getBytes("iso-8859-1"), "GBK");
		} catch (UnsupportedEncodingException e) {
			return null;
		}
	}
	
	public static boolean isNeedConvert(char para) {
		return ((para & (0x00FF)) != para);
	}
	
	/**
	 * 
	 * @param str
	 * @return String
	 */
	public static String GBK2Unicode(String str) {
		if(str == null){
			return "";
		}
		StringBuffer result = new StringBuffer();
		for (int i = 0; i < str.length(); i++) {
			char chr1 = (char) str.charAt(i);

			if (!isNeedConvert(chr1)) {
				result.append(chr1);
				continue;
			}

			result.append("\\u" + Integer.toHexString((int) chr1));
		}

		return result.toString();
	}

	/**
	 * 
	 * @param dataStr
	 * @return String
	 */
	public static String Unicode2GBK(String dataStr) {
		if(dataStr == null){
			return "";
		}
		int index = 0;
		StringBuffer buffer = new StringBuffer();

		int li_len = dataStr.length();
		while (index < li_len) {
			if (index >= li_len - 1
					|| !"\\u".equals(dataStr.substring(index, index + 2))) {
				buffer.append(dataStr.charAt(index));

				index++;
				continue;
			}

			String charStr = "";
			charStr = dataStr.substring(index + 2, index + 6);

			char letter = (char) Integer.parseInt(charStr, 16);

			buffer.append(letter);
			index += 6;
		}

		return buffer.toString();
	}
	
	/**
	 * utf-8 转unicode 
	 * 
	 * @param inStr
	 * @return String
	 */
	public static String utf8ToUnicode(String inStr) {
		char[] myBuffer = inStr.toCharArray();

		StringBuffer sb = new StringBuffer();
		for (int i = 0; i < inStr.length(); i++) {
			UnicodeBlock ub = UnicodeBlock.of(myBuffer[i]);
			if (ub == UnicodeBlock.BASIC_LATIN) {
				sb.append(myBuffer[i]);
			} else if (ub == UnicodeBlock.HALFWIDTH_AND_FULLWIDTH_FORMS) {
				int j = (int) myBuffer[i] - 65248;
				sb.append((char) j);
			} else {
				short s = (short) myBuffer[i];
				String hexS = Integer.toHexString(s);
				String unicode = "\\u" + hexS;
				sb.append(unicode.toLowerCase());
			}
		}
		return sb.toString();
	}

	/**
	 * 
	 * @param theString
	 * @return String
	 */
	public static String unicodeToUtf8(String theString) {
		char aChar;
		int len = theString.length();
		StringBuffer outBuffer = new StringBuffer(len);
		for (int x = 0; x < len;) {
			aChar = theString.charAt(x++);
			if (aChar == '\\') {
				aChar = theString.charAt(x++);
				if (aChar == 'u') {
					// Read the xxxx
					int value = 0;
					for (int i = 0; i < 4; i++) {
						aChar = theString.charAt(x++);
						switch (aChar) {
						case '0':
						case '1':
						case '2':
						case '3':
						case '4':
						case '5':
						case '6':
						case '7':
						case '8':
						case '9':
							value = (value << 4) + aChar - '0';
							break;
						case 'a':
						case 'b':
						case 'c':
						case 'd':
						case 'e':
						case 'f':
							value = (value << 4) + 10 + aChar - 'a';
							break;
						case 'A':
						case 'B':
						case 'C':
						case 'D':
						case 'E':
						case 'F':
							value = (value << 4) + 10 + aChar - 'A';
							break;
						default:
							throw new IllegalArgumentException(
									"Malformed   \\uxxxx   encoding.");
						}
					}
					outBuffer.append((char) value);
				} else {
					if (aChar == 't')
						aChar = '\t';
					else if (aChar == 'r')
						aChar = '\r';
					else if (aChar == 'n')
						aChar = '\n';
					else if (aChar == 'f')
						aChar = '\f';
					outBuffer.append(aChar);
				}
			} else
				outBuffer.append(aChar);
		}
		return outBuffer.toString();
	}
	
	public static String gbk2utf8(String gbk) {
		String l_temp = GBK2Unicode(gbk);
		l_temp = unicodeToUtf8(l_temp);

		return l_temp;
	}

	public static String utf82gbk(String utf) {
		String l_temp = utf8ToUnicode(utf);
		l_temp = Unicode2GBK(l_temp);

		return l_temp;
	}
	
	/**
	 * 
	 * @description: 转换对象的属性值为Unicode oracle us7ascii 字符集下用
	 * @param model
	 * @param flag 1 string to Unicode;str2ISO88591  0 or 2 Unicode to string;ISO885912str
	 * @author kool.zhao
	 * @createDate 2017年2月8日;下午12:16:58
	 */
	public static void converFieldValue(Object model, int flag){
		Field[] field = model.getClass().getDeclaredFields(); // 获取实体类的所有属性，返回Field数组
        try {
        	 List<Field> list = new ArrayList<Field>();
             for (int i = 0; i < field.length; i++) {
                 list.add(field[i]);
             }
             
             String superName = model.getClass().getSuperclass().getSimpleName();
             if("TreeEntity".equals(superName)){
            	 list.add(model.getClass().getSuperclass().getDeclaredField("name"));
            	 list.add(model.getClass().getSuperclass().getSuperclass().getDeclaredField("remarks"));
            	 list.add(model.getClass().getSuperclass().getSuperclass().getDeclaredField("createBy"));
            	 list.add(model.getClass().getSuperclass().getSuperclass().getDeclaredField("updateBy"));
             }else{
            	 list.add(model.getClass().getSuperclass().getDeclaredField("remarks"));
            	 list.add(model.getClass().getSuperclass().getDeclaredField("createBy"));
            	 list.add(model.getClass().getSuperclass().getDeclaredField("updateBy"));
             }
             
            for (Field f:list) { // 遍历所有属性
                String name = f.getName(); // 获取属性的名字
                name = name.substring(0, 1).toUpperCase() + name.substring(1); // 将属性的首字符大写，方便构造get，set方法
                String type = f.getGenericType().toString(); // 获取属性的类型
                if (!Modifier.isStatic(f.getModifiers()) && type.equals("class java.lang.String")) { // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = model.getClass().getMethod("get" + name);
                    String value = (String) m.invoke(model); // 调用getter方法获取属性值
                    if (value != null) {
                        m = model.getClass().getMethod("set"+name,String.class);
                        if(flag == 1 && isChinese(value)){
//                        	 m.invoke(model, GBK2Unicode(value));
                        	 m.invoke(model, str2ISO88591(value));
                        }
                        if(flag == 2 && !isCharOrNumber(value) && !isChinese(value)){
                        /*	if(value.contains("\\")){
                        		m.invoke(model, Unicode2GBK(value));
                        	}*/
                        	m.invoke(model, ISO885912str(value));
                        }
                    }
                }
                
                if (flag == 2 && type.contains(".entity.")) {//说明是实体类
                	 Method m = model.getClass().getMethod("get" + name);
                	 Object result = m.invoke(model);
                	 if(result != null){
                		 if(result instanceof DataEntity){
                              converFieldValue(result, 2);
                         }
                	 }
                }
                // 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断 type.equals("class java.lang.Integer") type.equals("class java.lang.Boolean") type.equals("class java.util.Date")
            }
        } catch (NoSuchMethodException e) {
//            e.printStackTrace();
        } catch (NoSuchFieldException e) {
//			e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
	}
	
	public static void converFieldValue(Object model){
		Field[] field = model.getClass().getDeclaredFields(); // 获取实体类的所有属性，返回Field数组
        try {
        	 List<Field> list = new ArrayList<Field>();
             for (int i = 0; i < field.length; i++) {
                 list.add(field[i]);
             }
             
             String superName = model.getClass().getSuperclass().getSimpleName();
             if("TreeEntity".equals(superName)){
            	 list.add(model.getClass().getSuperclass().getDeclaredField("name"));
            	 list.add(model.getClass().getSuperclass().getSuperclass().getDeclaredField("remarks"));
             }else{
            	 list.add(model.getClass().getSuperclass().getDeclaredField("remarks"));
             }
             
            for (Field f:list) { // 遍历所有属性
                String name = f.getName(); // 获取属性的名字
                name = name.substring(0, 1).toUpperCase() + name.substring(1); // 将属性的首字符大写，方便构造get，set方法
                String type = f.getGenericType().toString(); // 获取属性的类型
                if (!Modifier.isStatic(f.getModifiers()) && type.equals("class java.lang.String")) { // 如果type是类类型，则前面包含"class "，后面跟类名
                    Method m = model.getClass().getMethod("get" + name);
                    String value = (String) m.invoke(model); // 调用getter方法获取属性值
                    if (value != null) {
                        m = model.getClass().getMethod("set"+name,String.class);
                        if(!isCharOrNumber(value) && !isChinese(value)){
                        	m.invoke(model, ISO885912str(value));
                        }
                    }
                }
                
                // 如果有需要,可以仿照上面继续进行扩充,再增加对其它类型的判断 type.equals("class java.lang.Integer") type.equals("class java.lang.Boolean") type.equals("class java.util.Date")
            }
        } catch (NoSuchMethodException e) {
//            e.printStackTrace();
        } catch (NoSuchFieldException e) {
//			e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
	}
	
    public static String getEncoding(String str) {  
        String encode = "GB2312";  
        try {  
            if (str.equals(new String(str.getBytes(encode), encode))) {  
                String s = encode;  
                return s;  
            }  
        } catch (Exception exception) {  
        }  
        encode = "ISO-8859-1";  
        try {  
            if (str.equals(new String(str.getBytes(encode), encode))) {  
                String s1 = encode;  
                return s1;  
            }  
        } catch (Exception exception1) {  
        }  
        encode = "UTF-8";  
        try {  
            if (str.equals(new String(str.getBytes(encode), encode))) {  
                String s2 = encode;  
                return s2;  
            }  
        } catch (Exception exception2) {  
        }  
        encode = "GBK";  
        try {  
            if (str.equals(new String(str.getBytes(encode), encode))) {  
                String s3 = encode;  
                return s3;  
            }  
        } catch (Exception exception3) {  
        }  
        return "";  
    } 
    
}
